import os
import paramiko
import time

def remoteBackup(ssh, sftp, remotePath, remoteBackupPath,backMaxNum,buildInfo):
    try:
        # 检查需要备份备份文件夹是否存在，不存在则跳过
        try:
            sftp.stat(remotePath)
        except FileNotFoundError:
            sftp.mkdir(remotePath)
            buildInfo['log'] += f"远程文件夹不存在 创建 {remotePath};"
            print(f"远程文件夹 {remotePath} 不存在,创建 {remotePath}")
        # 检查备份文件夹是否存在，不存在则创建
        try:
            sftp.stat(remoteBackupPath)
        except FileNotFoundError:
            sftp.mkdir(remoteBackupPath)
            buildInfo['log'] += f"远程备份文件夹不存在 创建 {remoteBackupPath};"
            print(f"远程备份文件夹 {remoteBackupPath} 不存在,创建 {remoteBackupPath}")

        # 获取当前时间作为后缀
        timestamp = time.strftime("%Y-%m-%d-%H-%M-%S")
        # 获取远程文件夹名称
        folder_name = os.path.basename(remotePath)
        backup_folder_name = f"{folder_name}_{timestamp}"
        backup_path = os.path.join(remoteBackupPath, backup_folder_name).replace('\\', '/')

        # 使用 SSH 命令进行备份（对于 Linux 服务器）
        stdin, stdout, stderr = ssh.exec_command(f'cp -r {remotePath} {backup_path}')
        exit_status = stdout.channel.recv_exit_status()
        if exit_status == 0:
            print(f"备份成功，备份路径: {backup_path}")
            buildInfo['log'] += "备份成功;"
            # 检查备份文件夹数量，若超过 10 个则删除最旧的备份
            check_and_clean_backups(ssh, remoteBackupPath,backMaxNum)

            # 删除原文件夹
            stdin, stdout, stderr = ssh.exec_command(f'rm -rf {remotePath}')
            delete_exit_status = stdout.channel.recv_exit_status()
            if delete_exit_status == 0:
                buildInfo['log'] += "原文件夹 删除成功"
                print(f"原文件夹 {remotePath} 删除成功")
            else:
                buildInfo['log'] += "原文件夹 删除失败"
                buildInfo['status'] = '0'
                print(f"原文件夹 {remotePath} 删除失败，错误信息: {stderr.read().decode('utf-8')}")
        else:
            buildInfo['log'] += "备份失败;"
            buildInfo['status'] = '0'
            print(f"备份失败，错误信息: {stderr.read().decode('utf-8')}")
        
    except Exception as e:
        buildInfo['log'] += "上传过程中出现错误;"
        buildInfo['status'] = '0'
        print(f"上传过程中出现错误: {e}")

def check_and_clean_backups(ssh, remoteBackupPath,backMaxNum):
    try:
        # 获取备份文件夹下的所有备份文件夹列表
        stdin, stdout, stderr = ssh.exec_command(f'ls -1t {remoteBackupPath}')
        backup_folders = stdout.read().decode('utf-8').strip().split('\n')
        backMaxNumInt = int(backMaxNum)
        # 如果备份文件夹数量超过 backMaxNum 个
        if len(backup_folders) > backMaxNumInt:
            # 获取需要删除的最旧的备份文件夹列表
            folders_to_delete = backup_folders[backMaxNumInt:]
            for folder in folders_to_delete:
                folder_path = os.path.join(remoteBackupPath, folder).replace('\\', '/')
                # 使用 SSH 命令删除最旧的备份文件夹
                stdin, stdout, stderr = ssh.exec_command(f'rm -rf {folder_path}')
                exit_status = stdout.channel.recv_exit_status()
                if exit_status == 0:
                    print(f"删除旧备份成功: {folder_path}")
                else:
                    print(f"删除旧备份失败，错误信息: {stderr.read().decode('utf-8')}")
    except Exception as e:
        print(f"检查和清理备份时出现错误: {e}")

# 
def upload_folder(job,buildInfo):
    localPath = job['localPath']
    remotePath = job['remotePath']
    remoteBackupPath = job['remoteBackupPath']
    hostname = job['host']
    username = job['username']
    password = job['password']
    remoteCommand = job['remoteCommand']
    backMaxNum = job['backMaxNum']
    
    # 创建 SSH 客户端对象
    ssh = paramiko.SSHClient()
    # 允许连接不在 know_hosts 文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # 连接服务器
    ssh.connect(hostname=hostname, username=username, password=password)
    # 创建 SFTP 客户端对象
    sftp = ssh.open_sftp()

    try:
        # 先备份远程文件夹
        remoteBackup(ssh, sftp, remotePath, remoteBackupPath,backMaxNum, buildInfo)

        # 遍历本地文件夹
        for root, dirs, files in os.walk(localPath):
            # 计算相对路径
            relative_path = os.path.relpath(root, localPath).replace('\\', '/').replace('.', '')
            remote_dir = os.path.join(remotePath, relative_path).replace('\\', '/')

            try:
                # 在服务器上创建对应的目录
                sftp.mkdir(remote_dir)
            except FileExistsError:
                pass

            # 上传文件
            for file in files:
                local_file_path = os.path.join(root, file)
                remote_file_path = os.path.join(remote_dir, file).replace('\\', '/')
                sftp.put(local_file_path, remote_file_path)

        print("文件夹上传成功！")
        buildInfo['log'] += '文件夹上传成功;'
    except Exception as e:
        buildInfo['log'] += '文件夹上传失败;'
        buildInfo['status'] = '0'
        print(f"上传过程中出现错误: {e}")
    # 执行远程服务器上的命令 remoteCommand 这个字段  如果存在此字段的话
    if remoteCommand  is not None and remoteCommand != '' and  buildInfo['status'] == '1' :
        try:
            stdin, stdout, stderr = ssh.exec_command(remoteCommand)
            exit_status = stdout.channel.recv_exit_status()
            if exit_status == 0:
                print(f"远程服务器上的命令({remoteCommand})执行成功 输出如下")
                print(stdout.read().decode())
                buildInfo['log'] += f"远程服务器上的命令执行成功 ({stdout.read().decode()});"
            else:
                print(f"远程服务器上的命令执行失败，错误信息: {stderr.read().decode('utf-8')}")
        except Exception as e:
            buildInfo['log'] += f"远程服务器上的命令执行失败，错误信息: {e};"
            buildInfo['status'] = '0'
            print(f"远程服务器上的命令执行失败，错误信息: {e}")
    # 关闭 SFTP 连接
    sftp.close()
    # 关闭 SSH 连接
    ssh.close()